/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.bff.designtime.generator.core.rtgen.managergenerator.assembler.method;


import com.inspur.edp.bef.component.detailcmpentity.vm.VMComponent;
import com.inspur.edp.bef.component.detailcmpentity.vm.VMMethod;
import com.inspur.edp.bff.designtime.generator.core.VmCoreGenContext;
import com.inspur.edp.caf.generator.baseInfo.ParameterInfo;
import com.inspur.edp.caf.generator.baseInfo.TypeInfo;
import com.inspur.edp.caf.generator.method.ClassMethodGenerator;
import com.inspur.edp.formserver.viewmodel.action.MappedCdpAction;
import com.inspur.edp.formserver.viewmodel.action.ViewModelAction;
import com.inspur.edp.formserver.viewmodel.collection.VMActionCollection;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import org.eclipse.jdt.core.dom.*;

import java.util.ArrayList;
import java.util.Arrays;

public abstract class BaseGetActionsGenerator extends ClassMethodGenerator {
    private static final String ResultParamName = "actions";
    private VMActionCollection actions;
    private String defaultActionId;
    protected VmCoreGenContext parentGenContext;

    public BaseGetActionsGenerator(VMActionCollection actions, String defaultActionId, VmCoreGenContext parentGenContext) {
        this.actions = actions;
        this.defaultActionId = defaultActionId;
        this.parentGenContext = parentGenContext;
    }

    protected abstract java.lang.Class getActionType();

    protected abstract java.lang.Class getContextParamType();

    protected abstract String getContextParamName();

    @Override
    protected final ArrayList<Modifier.ModifierKeyword> getAccessModifiers() {
        return new java.util.ArrayList<>(java.util.Arrays.asList(new Modifier.ModifierKeyword[]{Modifier.ModifierKeyword.PROTECTED_KEYWORD}));
    }

    @Override
    protected boolean getIsOverride() {
        return true;
    }

    @Override
    protected ArrayList<ParameterInfo> getParameterCollection() {
        ParameterInfo parameterInfo = new ParameterInfo();
        parameterInfo.setParamName(getContextParamName());
        parameterInfo.setParamType(new TypeInfo(getContextParamType()));
        return new ArrayList<>(Arrays.asList(new ParameterInfo[]{parameterInfo}));
    }

    /*ArralyList<ChangeMappingAction> list= new ArrayList<ChangeMappingAction>();
        list.add(new XX());
        return list;*/
    @Override
    protected Block buildMethodBody() {
        Block block = ast.newBlock();
        buildNewListStatement(block);
        buildAddActionsStatements(block);
        buildReturnListStatements(block);
        return block;
    }

    private void buildNewListStatement(Block block) {
        VariableDeclarationFragment variableDeclarationFragment = ast.newVariableDeclarationFragment();
        variableDeclarationFragment.setName(ast.newSimpleName("list"));

        ClassInstanceCreation classInstanceCreation = ast.newClassInstanceCreation();
        ParameterizedType parameterizedType = ast.newParameterizedType(ast.newSimpleType(ast.newName(ArrayList.class.getTypeName())));
        parameterizedType.typeArguments().add(new TypeInfo(getActionType()).getType(ast));
        classInstanceCreation.setType(parameterizedType);

        variableDeclarationFragment.setInitializer(classInstanceCreation);

        VariableDeclarationStatement variableDeclarationStatement = ast.newVariableDeclarationStatement(variableDeclarationFragment);
        ParameterizedType parameterizedType1 = ast.newParameterizedType(ast.newSimpleType(ast.newName(ArrayList.class.getTypeName())));
        parameterizedType1.typeArguments().add(new TypeInfo(getActionType()).getType(ast));
        variableDeclarationStatement.setType(parameterizedType1);

        block.statements().add(variableDeclarationStatement);
    }

    private void buildAddActionsStatements(Block block) {

        for (int i = 0; i < actions.size(); i++) {

            ViewModelAction action = actions.get(i);
            String actionType;
            if (action.getID().equals(defaultActionId))
                actionType = DefaultActionUtils.getDefaultActionType().get(defaultActionId).getTypeName();
            else
                actionType = getActionTypeName(action);

            buildAddActionStatement(block, actionType);
        }
        buildExtendAddActionStatements(block);
    }

    protected void buildAddActionStatement(Block block, String actionType){
        MethodInvocation methodInvocation = ast.newMethodInvocation();
        methodInvocation.setName(ast.newSimpleName("add"));
        methodInvocation.setExpression(ast.newSimpleName("list"));
        ClassInstanceCreation classInstanceCreation = ast.newClassInstanceCreation();
        classInstanceCreation.setType(ast.newSimpleType(ast.newName(actionType)));
        classInstanceCreation.arguments().add(ast.newSimpleName(getContextParamName()));

        methodInvocation.arguments().add(classInstanceCreation);
        block.statements().add(ast.newExpressionStatement(methodInvocation));
    }

    protected void buildExtendAddActionStatements(Block block){

    }

    private String getActionTypeName(ViewModelAction action) {
        MappedCdpAction mappedCdpAction = (MappedCdpAction) action;
        GspMetadata metadata = parentGenContext.getVmGenContext().getMetadataPool().getMetadata(mappedCdpAction.getComponentPkgName(), mappedCdpAction.getComponentEntityId());
        if (metadata == null)
            throw new RuntimeException("未找到构件元数据[" + mappedCdpAction.getCode() + "]，元数据id为" + mappedCdpAction.getComponentEntityId());
        VMComponent compMetadata = (VMComponent) metadata.getContent();
        VMMethod method = compMetadata.getVmMethod();
        return method.getClassName();
    }

    private void buildReturnListStatements(Block block) {
        ReturnStatement returnStatement = ast.newReturnStatement();
        returnStatement.setExpression(ast.newSimpleName("list"));
        block.statements().add(returnStatement);
    }
}
